package com.infolab.aims.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.infolab.aims.common.PaginationHelper;
import com.infolab.aims.common.QueryHelper;
import com.infolab.aims.common.bean.SearchCriteria;
import com.infolab.aims.common.bean.SearchResult;
import com.infolab.aims.domain.Archive;
import com.infolab.aims.domain.ArchivePK;
import com.infolab.aims.service.intf.ArchiveService;
import com.infolab.aims.web.ArchiveController;

@Service
@Transactional
public class ArchiveServiceImpl implements ArchiveService {

	Log logger = LogFactory.getLog(getClass());
	@PersistenceContext
	private EntityManager em;

	public List<Archive> searchArchiveCriteria(SearchCriteria searchCriteria) {

		if (searchCriteria == null)
			searchCriteria = new SearchCriteria();
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<Archive> cq = cb.createQuery(Archive.class);

		Root<Archive> root = cq.from(Archive.class);
		List<Predicate> criteria = new ArrayList<Predicate>();

		if (searchCriteria.getSearchCriteria("modifiedBy") != null) {
			ParameterExpression<String> p = cb.parameter(String.class, "modifiedBy");
			criteria.add(cb.equal(root.get("modifiedBy"), p));
		}
		
		if (searchCriteria.getSearchCriteria("type") != null) {
			ParameterExpression<String> p = cb.parameter(String.class, "type");
			criteria.add(cb.equal(root.get("type"), p));
		}

		cq.select(root);

		if (criteria.size() == 0) {
		} else if (criteria.size() == 1) {
			cq.where(criteria.get(0));
		} else {
			cq.where(cb.and(criteria.toArray(new Predicate[0])));
		}

		Query query = em.createQuery(cq);

		if (searchCriteria.getSearchCriteria("modifiedBy") != null) {
			String tmp = (String) searchCriteria.getSearchCriteria("modifiedBy");
			query.setParameter("modifiedBy", tmp);
		}
		
		if (searchCriteria.getSearchCriteria("type") != null) {
			String tmp = (String) searchCriteria.getSearchCriteria("type");
			query.setParameter("type", tmp);
		}

		if (searchCriteria.getMaxRow() != null)
			query.setMaxResults(searchCriteria.getMaxRow());

		return query.getResultList();

	}


	public static class ArchivePaginationHelper extends PaginationHelper<Archive> {

		@Override
		public String[] getValidColumnName() {
			return new String[] { "archivePK.archiveId", "archiveCode", "archiveName", "archivePK.type", "modifiedBy", "dateModified" };
		}

		@Override
		public String[] getValidSortName() {
			return new String[] { "archivePK.archiveId", "archiveCode", "archiveName", "archivePK.type", "modifiedBy", "dateModified" };
		}

		@Override
		public String getDefaultSortName() {
			return "modifiedBy desc";
		}

		@Override
		public QueryHelper getQueryHelper() {
			QueryHelper queryHelper = new QueryHelper();
			queryHelper.select("select new Archive(archivePK.archiveId, archivePK.type, archiveCode, archiveName,  modifiedBy, dateModified) from Archive archive");
			return queryHelper;
		}
	}

	public SearchResult searchArchive(SearchCriteria searchCriteria) {
		ArchivePaginationHelper helper = new ArchivePaginationHelper();
		if (searchCriteria.getCurPage() == null)
			searchCriteria.setCurPage(1);
		return helper.getSearchResultFromQueryHelper(em, searchCriteria);
	}

	public void updateArchive(ArchivePK archivePK) {

		String updateColumn = ArchiveController.MODULE_ID.get(archivePK.getType());
		Query query = em.createQuery("update " + archivePK.getType() +" set active=true where "+updateColumn+"=:id");
		query.setParameter("id", archivePK.getArchiveId());
		query.executeUpdate();
	}

}
